/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "SQLitePlugin.h"
#include "cJSON.h"


REGISTER_PLUGIN_CLASS(SQLitePlugin)

bool SQLitePlugin::execute(const string&  actionAsString, cJSON* args, CallbackContext cbc)
{
    Action action;
    if(actionAsString == "echoStringValue") {
        action = Action::echoStringValue;
    }
    
    if(actionAsString == "open") {
        action = Action::open;
    }
    
    if(actionAsString == "close") {
        action = Action::close;
    }
    
    if(actionAsString == "delete") {
        action = Action::del;
    }
    
    if(actionAsString == "executeSqlBatch") {
        action = Action::executeSqlBatch;
    }
    
    if(actionAsString == "backgroundExecuteSqlBatch") {
        action = Action::backgroundExecuteSqlBatch;
    }
    
    if(actionAsString == "echoStringValue") {
        action = Action::echoStringValue;
    }
    
    if(actionAsString == "echoStringValue") {
        action = Action::echoStringValue;
    }
    
    return executeAndPossiblyThrow(action, args, cbc);
}
bool SQLitePlugin::executeAndPossiblyThrow(Action action, cJSON* args, CallbackContext cbc)
{
    bool status = true;
    cJSON* o;
    string echoValue;
    string dbname;
    switch(action) {
    case echoStringValue:
        o = cJSON_GetArrayItem(args, 0);
        echoValue = cJSON_GetObjectItem(o, "value")->valuestring;
        cbc.success(echoValue);
        break;
    case open:
        o = cJSON_GetArrayItem(args, 0);
        dbname = cJSON_GetObjectItem(o, "name")->valuestring;
        startDatabase(dbname, o, cbc);
        break;
    case close:
        o = cJSON_GetArrayItem(args, 0);
        dbname = cJSON_GetObjectItem(o, "path")->valuestring;
        closeDatabase(dbname, cbc);
        break;
     case del:
        o = cJSON_GetArrayItem(args, 0);
        dbname = cJSON_GetObjectItem(o, "path")->valuestring;
        deleteDatabase(dbname, cbc);
        break;
    case executeSqlBatch:
    case backgroundExecuteSqlBatch:
        {
            cJSON* allargs = cJSON_GetArrayItem(args, 0);
            cJSON* dbargs = cJSON_GetObjectItem(allargs, "dbargs");
            dbname = cJSON_GetObjectItem(dbargs, "dbname")->valuestring;
            cJSON* txargs = cJSON_GetObjectItem(allargs, "executes");
            if(txargs == NULL) {
                cbc.error("INTERNAL PLUGIN ERROR：missing executes list");
            } else {
                int len = cJSON_GetArraySize(txargs);
                vector<string> queries;
                vector<cJSON*> jsonParams;
                for(int i=0; i<len; i++) {
                    cJSON* a = cJSON_GetArrayItem(txargs,i);
                    queries.push_back(cJSON_GetObjectItem(a, "sql")->valuestring);
                    cJSON* params = cJSON_Duplicate(cJSON_GetObjectItem(a, "params"), 1);
                    jsonParams.push_back(params);
                }
                //完成任务后释放指针
                DBQuery* q = new DBQuery(queries, jsonParams, cbc);
                if(m_dbrmap->find(dbname) != m_dbrmap->end()) {
                    DBRunner* r = (*m_dbrmap)[dbname];
                    r->AddTask(q);
                } else {
                   cbc.error("INTERNAL PLUGIN ERROR:datase not open");
                }
            }
            break;
        }
    }
    return status;
}
void SQLitePlugin::startDatabase(string dbname, cJSON* options, CallbackContext cbc)
{
    if(m_dbrmap->find(dbname) != m_dbrmap->end()) {
        char szBuf[256];
        sprintf(szBuf, "INTERNAL ERROR:database already open for dbName:%s", dbname.c_str());
        //cbc.error(szBuf);
        cbc.success();
    } else {
        DBRunner* r = new DBRunner(dbname);
        (*m_dbrmap)[dbname] = r;
        r->SetPoolSize(20);
        r->Start(NULL);
        cbc.success();
    }
}
void SQLitePlugin::closeDatabase(string dbname, CallbackContext cbc)
{
    map<string, DBRunner*>::iterator it = m_dbrmap->find(dbname);
    if(it != m_dbrmap->end()) {
        DBRunner* r = (*m_dbrmap)[dbname];
        r->Stop();
        m_dbrmap->erase(it);
        delete r;
        cbc.success();//打开后不再关闭，有操作系统关闭。
    } else {
        cbc.success();
    }
}

void SQLitePlugin::deleteDatabase(string dbname, CallbackContext cbc)
{
    map<string, DBRunner*>::iterator it = m_dbrmap->find(dbname);
    if(it != m_dbrmap->end()) {
        DBRunner* r = (*m_dbrmap)[dbname];
        r->Stop();
        m_dbrmap->erase(it);
        delete r;
    } else {
        cbc.success();
    }
}